home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_9.zip
/
AGGR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-27
|
58KB
|
1,821 lines
/*
* Copyright (C) 1985-1992 New York University
*
* This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
* warranty (none) and distribution info and also the GNU General Public
* License for more details.
*/
/* aggr.c : translation of aggr.stl */
#define GEN
#include "hdr.h"
#include "vars.h"
#include "gvars.h"
#include "attr.h"
#include "miscp.h"
#include "setp.h"
#include "gutilp.h"
#include "gnodesp.h"
#include "gmiscp.h"
#include "smiscp.h"
#include "initobjp.h"
#include "expandp.h"
#include "aggrp.h"
static int tup_eq(Tuple, Tuple);
static Tuple aggr_choice(Node, Tuple, Symbol);
static int needs_subtype(Node, Node, Symbol);
static Node new_type_choice(Node, Symbol, Tuple);
static Tuple aggr_type(Node, Tuple);
static Tuple same_bounds_check(Symbol, Tuple, Tuple);
static Tuple in_bounds_check(Tuple, Tuple, int *);
static Tuple aggr_eval(Node, Tuple, Tuple, Node, Symbol, int);
static Node new_index_bound_node(Const, int, Symbol);
/* changes
* 13-mar-85 shields
* change 'index_type' to 'indx_type' since index_type is macro in sem.
*
* 18-6-86 ACD
* changed final loop over checks in 'same_bounds_check' to improve
* efficiency
*
* 19-6-86 ACD
* changed 'exists' to 'static_index' in 'aggr_eval' to improve clarity
*
* 22-6-86 ACD
* changed aggr_eval to allow for optimization of static and semi-static
* aggregates. If the aggregate is static and associations and components
* are static then the aggregate is 'optable'. A data segment will
* be created with the aggregate values in the data stack and will be
* assigned to the array at run time. The creation of the stack is done
* by array_ivalue in expr.c. aggr_eval unwinds the aggregate and changes
* it into a positional aggregate passing the correct information to
* array_ivalue. Array_ivalue uses the static_nodes to create the segment
* and appends additional assignment statements for any non-static components
* If there is an others clause,
* then it is used to 'fill-in' the missing associations.
*
* 24-6-86 ACD
* Added code to detect the following flags: static_assoc, array_size,
* static_component to be used in deciding whether to optimize or not.
* These are set in aggr_choice, in_bounds_check and check_static_comp
* (new routine) respectively. From this information the flag:
* optable are set. Ths is passed to aggr_eval
* to decide the level to optimize in attempt to evalaute a time-space
*/
void expand_array_aggregate(Node node) /*;expand_array_aggregate*/
{
/*
*
* This procedure normalizes the format of an array aggregate, and
* constructs the tree for the multiple range checks that may have
* to be performed before constructing the aggregate proper.
* The aggregate has the format : [positional_list, named_list, others]
*
* On exit from this procedure, the named_list has been expanded into
* code to perform range checks, and code to initialize the array
* components. The rules of the language require that this code be in
* fact elaborated first, that is to say before the elaboration of any
* components (including the positional ones).
* The positional part has been expanded to collect static components
* and give explicit indication of the index positions.
* The following takes place in sequence:
*
* a) expand code to evaluate named choices.
* b) obtain all index types.
* c) For multidimensional aggregates, verify that bounds of all
* subaggregates are the same.
* d) Verify that the aggregate bounds are compatible with type of
* indices.
* e) expand code to evaluate components. For named associations
* that are static, it is tempting to elaborate the array here,
* in full. This is probably impractical for large arrays. The
* current solution is to emit a case statement that assigns to
* individual components according to the choices.
* In the case of a single named component, a loop is emitted.
* The same holds for 'others' choice when present.
* This scheme clearly contains much room for optimization.
*
*/
Symbol type_name;
Tuple index_type_list, base_index_type_list, tup, decl_code, ntup;
Symbol comp_type, bt, al, obj_name;
Tuple new_subtypes;
Tuple index_type_sets;
Tuple init_code, new_pos, new_index_type_list, new_nam;
Node obj_node, pos_node, nam_node, comp_node, n, lnode;
Fortup ft1;
int optable;
int array_size;
#ifdef TRACE
if (debug_flag)
gen_trace_node("ARRAY_AGGREGATE", node);
#endif
/*
* STEP 1
* Initialize variables etc.
*/
type_name = N_TYPE(node);
index_type_list = index_types(type_name);
tup = SIGNATURE((Symbol) base_type(type_name));
base_index_type_list = (Tuple) tup[1];
comp_type = (Symbol)tup[2];
/*
* STEP 2
* Evaluate all choices first, including choices in subaggregates
* declaring anon subtypes when necessary. A tuple containing
* these declarations is returned.
*/
decl_code = aggr_choice(node, index_type_list, comp_type);
/*
* STEP 3
* Then gather all index subtypes for all dimensions. Add the
* code for the new subtypes created to tuple of declarations
*/
tup = aggr_type(node, index_type_list);
new_subtypes = (Tuple) tup[1];
index_type_sets = (Tuple) tup[2];
tup_free(tup); ntup = tup_add(decl_code, new_subtypes);
tup_free(decl_code); decl_code = ntup;
tup_free(new_subtypes); /* free after last use */
/*
* STEP 4
* Now check that all bounds for each dimension are the same. If bounds
* are dynamic, then a set of run-time checks are returned
*/
tup = same_bounds_check(type_name, index_type_list, index_type_sets);
init_code = (Tuple) tup[1];
new_index_type_list = (Tuple) tup[2];
/*
* STEP 5
* Is unconstrained or indices computed in same_bounds_check differ from
* those computed in aggr_type, then set the type of the aggregate to
* the index_types to created in same_bounds_check
*/
if (!tup_eq(index_type_list , new_index_type_list)
|| is_unconstrained(type_name)) {
bt = base_type(type_name);
al = ALIAS(type_name);
type_name = new_unique_name("type");
NATURE(type_name) = na_subtype;
TYPE_OF(type_name) = bt;
tup = tup_new(2);
tup[1] = (char *) new_index_type_list;
tup[2] = (char *) comp_type;
SIGNATURE(type_name) = tup;
ALIAS(type_name) = al;
decl_code=tup_with(decl_code, (char *)new_subtype_decl_node(type_name));
index_type_list = new_index_type_list;
N_TYPE(node) = type_name;
}
/*
* STEP 6
* Now test that the index_types computed belong to the base_index_types.
* If bounds are dynamic, then run_time checks are performed
*/
array_size = 1;
tup = in_bounds_check(index_type_list, base_index_type_list, &array_size);
ntup = tup_add(init_code, tup);
tup_free(init_code);
init_code = ntup;
tup_free(tup);
/*
* STEP 7
* Finally, expand assignments to individual components.
* Add to aggregate node the name of the object assigned to it. The
* variable, constant, or temporary to which the aggregate is
* assigned, will be bound to this name subsequently. This name has
* been put in the N_UNQ of the node by the FE. In the case of an
* aggregate appearing as the initial value of an object declaration,
* the name has been changed to the first name of the identifier list.
*/
obj_name = N_UNQ(node);
obj_node = new_name_node(obj_name);
if (NATURE(obj_name) == na_void) {
new_symbol(obj_name, na_obj, N_TYPE(node), (Tuple)0, (Symbol)0);
/* else another copy of the aggregate was already expanded.
* this is the case if the aggregate is a default expression used
* in several calls.
*/
}
optable = (array_size > 0 && array_size < MAX_STATIC_SIZE
&& !(is_unconstrained(comp_type)));
ntup = tup_add(init_code, aggr_eval(node, new_index_type_list, tup_new(0),
obj_node, comp_type, optable));
tup_free(init_code);
init_code = ntup;
/*
* STEP 8
* Sort the nodes that initialize components into those that are pure-
* ly static and those that require emission of assignment statements.
*/
new_pos = tup_new(0);
new_nam = tup_new(0);
FORTUP(